#include "MessageEditArea.h"
#include <QFileDialog>
#include <QHBoxLayout>
#include <QScrollBar>
#include "DataCenter.h"
#include "HistoryDialog.h"
#include "MainWidget.h"
#include "SoundRecorder.h"
#include "Toast.h"

using namespace model;
MessageEditArea::MessageEditArea()
{
    init_ui();
    init_signals_slots();
}

/// @brief 初始化UI界面
void MessageEditArea::init_ui()
{
    this->setFixedHeight(200);
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    this->setObjectName("message_edit");
    this->setStyleSheet(
        "QWidget {"
        "border-top: 1px solid #E9E9E9;"
        "}");
    /* 1. 添加放置顶部按钮的QWidget, 并向其中添加按钮 */
    QWidget* container_wiget = new QWidget();
    container_wiget->setFixedHeight(35);
    send_image_btn        = new QPushButton();
    send_speech_btn       = new QPushButton();
    send_file_btn         = new QPushButton();
    get_history_btn       = new QPushButton();
    QHBoxLayout* h_layout = new QHBoxLayout();
    h_layout->setAlignment(Qt::AlignLeft);
    container_wiget->setLayout(h_layout);
    h_layout->setSpacing(15);
    h_layout->setContentsMargins(15, 5, 10, 0);
    h_layout->addWidget(send_file_btn);
    h_layout->addWidget(send_image_btn);
    h_layout->addWidget(send_speech_btn);
    QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed);
    h_layout->addSpacerItem(spacer);
    h_layout->addWidget(get_history_btn);
    /* 2. 设置上方按钮的属性 */
    QSize size(30, 30);
    send_image_btn->setIconSize(size);
    send_image_btn->setFixedSize(size);
    send_speech_btn->setIconSize(size);
    send_speech_btn->setFixedSize(size);
    send_file_btn->setIconSize(size);
    send_file_btn->setFixedSize(size);
    get_history_btn->setIconSize(size);
    get_history_btn->setFixedSize(size);
    container_wiget->setStyleSheet(
        "QPushButton {"
        "border: none;"
        "background-repeat: no-repeat;"
        "background-position: center center;"
        "}");
    send_image_btn->setStyleSheet(
        "QPushButton {"
        "border-image:url(:/image/image.png);"
        "}"
        "QPushButton:hover {"
        "border-image:url(:/image/image_active.png);"
        "}");
    send_speech_btn->setStyleSheet(
        "QPushButton {"
        "border-image:url(:/image/speech.png);"
        "}"
        "QPushButton:hover {"
        "border-image:url(:/image/speech_active.png);"
        "}");
    send_file_btn->setStyleSheet(
        "QPushButton {"
        "border-image:url(:/image/file.png);"
        "}"
        "QPushButton:hover {"
        "border-image:url(:/image/file_active.png);"
        "}");
    get_history_btn->setStyleSheet(
        "QPushButton {"
        "border-image:url(:/image/history.png);"
        "}"
        "QPushButton:hover {"
        "border-image:url(:/image/history_active.png);"
        "}");
    /* 3. 设置文本编辑框的属性 */
    text_edit = new CustomTextEdit();
    text_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);  // 设置完Expanding后该编辑框会把所有上下两组的按钮之间的空白填满
    text_edit->setStyleSheet(
        "QPlainTextEdit{ "
        "font-size: 14px;"
        "border: none;"
        "padding-left: 15px;"
        "padding-right: 15px;"
        "}");
    text_edit->verticalScrollBar()
        ->setStyleSheet(
            "QScrollBar:vertical {"
            "    width: 6px;"
            "    background: transparent;"
            "    border-radius: 3px;"
            "}"
            "QScrollBar::handle:vertical {"
            "    background-color: #d4d4d4;"
            "    border-radius: 3px;"
            "    min-height: 15px;"
            "    max-height: 15px;"
            "}"
            "QScrollBar::add-line:vertical,"
            "QScrollBar::sub-line:vertical {"
            "    height: 0px;"  // 通过设置高度为0隐藏箭头
            "    background: none;"
            "}");
    text_edit->horizontalScrollBar()->setStyleSheet(
        "QScrollBar:horizontal {"
        "    width: 0px;"
        "    height: 0px;"
        "}");
    /* 4. 设置提交按钮属性 */
    send_btn = new QPushButton();
    send_btn->setText("发送");
    send_btn->setFixedSize(QSize(80, 27));
    send_btn->setStyleSheet(
        "QPushButton {"
        "font-size: 14px;"
        "background-color: #0099FF;"
        "border-radius: 5px;"
        "}"
        "QPushButton:hover {"
        "background-color: #0093F5;"
        "}"
        "QPushButton:pressed {"
        "background-color: #0086E0;"
        "}");
    /* 5. 添加布局, 把控件添加进去 */
    QVBoxLayout* v_layout = new QVBoxLayout();
    this->setLayout(v_layout);
    v_layout->setContentsMargins(0, 0, 15, 15);
    v_layout->setSpacing(0);
    v_layout->addWidget(container_wiget);
    v_layout->addWidget(text_edit);
    v_layout->addWidget(send_btn, 0, Qt::AlignRight | Qt::AlignVCenter);
    /* 设置发送按钮不可用 */
    send_btn->setEnabled(false);
    /* 获取 data_center */
    data_center = DataCenter::get_instance();
    /* 录音时的提示按钮 */
    recording_label = new QLabel("正在录制, 松开按钮结束");
    recording_label->setAlignment(Qt::AlignCenter);
    recording_label->setStyleSheet(
        "QLabel {"
        "font-size: 18px;"
        "color: #0099FF;"
        "border: none;"
        "}");
    v_layout->addWidget(recording_label);
    recording_label->hide();
}

/// @brief 连接信号槽
void MessageEditArea::init_signals_slots()
{
    /* 点击历史消息按钮 */
    connect(get_history_btn, &QPushButton::clicked, this, [this]() {
        if (data_center->get_cur_session_id() == "") {
            Toast::showMessage("当前未选中任何会话!");
            return;
        }
        HistoryDialog* history_dialog = new HistoryDialog(this);
        history_dialog->exec();  // 模态对话框
    });
    /* 点击发送按钮 */
    connect(send_btn, &QPushButton::clicked, this, &MessageEditArea::send_message);
    /* 点击发送图片按钮 */
    connect(send_image_btn, &QPushButton::clicked, this, &MessageEditArea::send_image_message);
    /* 点击发送文件按钮 */
    connect(send_file_btn, &QPushButton::clicked, this, &MessageEditArea::send_file_message);
    /* 按住发送语音按钮 */
    connect(send_speech_btn, &QPushButton::pressed,
            this, &MessageEditArea::handle_pressed_speech_btn);
    /* 松开发送语音按钮 */
    connect(send_speech_btn, &QPushButton::released,
            this, &MessageEditArea::handle_released_speech_btn);
    /* 录制结束, 从网络中发送消息 */
    connect(SoundRecorder::get_instance(), &SoundRecorder::sound_record_done,
            this, &MessageEditArea::send_speech_message);
    /* 文本编辑框中按下Enter键 */
    connect(text_edit, &CustomTextEdit::enter_pressed,
            this, &MessageEditArea::send_message);
    /* 收到发送成功信号 */
    connect(data_center, &DataCenter::send_message_done, this, &MessageEditArea::push_back_message, Qt::UniqueConnection);
    /* 收到别人发的消息 */
    connect(data_center, &DataCenter::receive_message_done, this, &MessageEditArea::push_back_message_other, Qt::UniqueConnection);
    /* text_edit 内容变化 */
    connect(text_edit, &CustomTextEdit::textChanged, this, &MessageEditArea::text_edit_changed);
}

/// @brief 发送消息
void MessageEditArea::send_message()
{
    /* 如果当前未选中任意一个会话, 给用户一个提示 */
    const QString cur_session_id = data_center->get_cur_session_id();
    if (cur_session_id.isEmpty()) {
        Toast::showMessage("请选择一个会话");
        return;
    }
    /* 发送消息, 文本内容的合法性已经在 text_edit_changed()检查过了 */
    data_center->send_text_message_async(cur_session_id, text_edit->toPlainText());
    text_edit->clear();
}

void MessageEditArea::send_image_message()
{
    /* 如果当前未选中任意一个会话, 给用户一个提示 */
    const QString cur_session_id = data_center->get_cur_session_id();
    if (cur_session_id.isEmpty()) {
        Toast::showMessage("请选择一个会话");
        return;
    }
    /* 弹出对话框, 选择图片 */
    QDir dir(QDir::currentPath());
    dir.cdUp();
    QString filter = "图片文件 (*.png *.jpg *.jpeg *.bmp)";
    QString path   = QFileDialog::getOpenFileName(this, "选择图片", dir.path(), filter);
    if (path.isEmpty()) {
        return;
    }
    const QByteArray image_data = read_file(path);
    /* 发送图片消息 */
    data_center->send_image_message_async(cur_session_id, image_data);
}

/// @brief 发送文件消息
void MessageEditArea::send_file_message()
{
    /* 如果当前未选中任意一个会话, 给用户一个提示 */
    const QString cur_session_id = data_center->get_cur_session_id();
    if (cur_session_id.isEmpty()) {
        Toast::showMessage("请选择一个会话");
        return;
    }
    /* 弹出对话框, 选择文件 */
    QDir dir(QDir::currentPath());
    dir.cdUp();
    QString filter = "所有文件 (*)";
    QString path   = QFileDialog::getOpenFileName(this, "选择文件", dir.path(), filter);
    if (path.isEmpty()) {
        return;
    }
    const QByteArray file_data = read_file(path);
    const QString    file_name = path.section('/', -1);
    /* 发送文件消息 */
    data_center->send_file_message_async(cur_session_id, file_data, file_name);
}

/// @brief 按下语音按钮, 开始录制音频
void MessageEditArea::handle_pressed_speech_btn()
{
    /* 如果当前未选中任意一个会话, 给用户一个提示 */
    const QString cur_session_id = data_center->get_cur_session_id();
    if (cur_session_id.isEmpty()) {
        Toast::showMessage("请选择一个会话");
        return;
    }
    /* 设置按钮的样式 */
    send_speech_btn->setStyleSheet(
        "QPushButton {"
        "border-image:url(:/image/speech_active.png);"
        "}");
    /* 将下面的文本输入框替换为“正在录制”Label */
    recording_label->show();
    text_edit->hide();
    send_btn->hide();
    /* 开始录制音频 */
    SoundRecorder* sound_recorder = SoundRecorder::get_instance();
    sound_recorder->start_record();
}

/// @brief 松开语音按钮, 停止录制音频, 发送音频消息
void MessageEditArea::handle_released_speech_btn()
{
    /* 如果当前未选中任意一个会话, 给用户一个提示 */
    const QString cur_session_id = data_center->get_cur_session_id();
    if (cur_session_id.isEmpty()) {
        Toast::showMessage("请选择一个会话");
        return;
    }
    /* 恢复最初的文本输入框 */
    send_speech_btn->setStyleSheet(
        "QPushButton {"
        "border-image:url(:/image/speech.png);"
        "}"
        "QPushButton:hover {"
        "border-image:url(:/image/speech_active.png);"
        "}");
    recording_label->hide();
    text_edit->show();
    send_btn->show();
    /* 停止录制 */
    SoundRecorder* sound_recorder = SoundRecorder::get_instance();
    sound_recorder->stop_record();
}

/// @brief 当前录制的音频文件准备好后, 发送音频消息
void MessageEditArea::send_speech_message(const QString& audio_path)
{
    //LOG() << "录制的音频文件路径: " << audio_path;
    /* 如果当前未选中任意一个会话, 给用户一个提示 */
    const QString cur_session_id = data_center->get_cur_session_id();
    if (cur_session_id.isEmpty()) {
        Toast::showMessage("请选择一个会话");
        return;
    }
    const QByteArray audio_data = read_file(audio_path);
    data_center->send_speech_message_async(cur_session_id, audio_data);
}
/// @brief 当文本输入框内容改变时, 改变发送按钮的显示
///        如果输入不合法, 始终让其 disable
void MessageEditArea::text_edit_changed()
{
    /* 如果当前未选中任何一个会话, 始终为 disable */
    const QString cur_session_id = data_center->get_cur_session_id();
    if (cur_session_id.isEmpty()) {
        send_btn->setEnabled(false);
        return;
    }
    /* 如果输入了空白内容, 始终为disable */
    const QString text = text_edit->toPlainText();
    if (text.trimmed().isEmpty()) {
        send_btn->setEnabled(false);
        return;
    }
    send_btn->setEnabled(true);
}

/// @brief 把自己发送的消息添加到消息显示区
void MessageEditArea::push_back_message(MessageType type, const QByteArray& content, const QString& extra_info)
{
    const QString chat_session_id = data_center->get_cur_session_id();
    if (chat_session_id.isEmpty()) {
        LOG() << "chat_session_id is empty";
        return;
    }
    /* 构造这条消息 */
    Message message = Message::make_message_object(type, chat_session_id,
                                                   *data_center->get_cur_user_info(), content, extra_info);
    /* 将这条消息添加到 data_center 中的列表中 */
    data_center->push_back_message_list(chat_session_id, message);
    /* 将这条消息添加到 MessageShowArea中 */
    MainWidget*      main_widget       = MainWidget::get_instance();
    MessageShowArea* message_show_area = main_widget->get_message_show_area();
    message_show_area->add_message(message, false);
    /* 发信号, 让SessionItem更新最后一条消息 */
    emit data_center->update_last_message(chat_session_id);
}

/// @brief 收到来自其它人发的消息
void MessageEditArea::push_back_message_other(const Message& message)
{
    /* 将这条消息添加到 MessageShowArea中 */
    MainWidget*      main_widget       = MainWidget::get_instance();
    MessageShowArea* message_show_area = main_widget->get_message_show_area();
    message_show_area->add_message(message, true);
}

void CustomTextEdit::keyPressEvent(QKeyEvent* event)
{
    if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
        if (event->modifiers() & Qt::ShiftModifier) {
            // Shift+Enter: 插入换行
            insertPlainText("\n");
        } else {
            // 检查内容合法性，如果当前没选中任何一个会话, 直接返回
            DataCenter*   data_center    = DataCenter::get_instance();
            const QString cur_session_id = data_center->get_cur_session_id();
            if (cur_session_id.isEmpty()) {
                return;
            }
            /* 如果输入了空白内容, 直接返回 */
            const QString text = toPlainText();
            if (text.trimmed().isEmpty()) {
                return;
            }
            // Enter: 发射信号
            emit enter_pressed();
            event->accept();  // 接受事件，防止默认处理
            return;
        }
    } else {
        QPlainTextEdit::keyPressEvent(event);
    }
}